home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1995 May / cd Ware (Juegos) Epimundo.iso / DOS / C / ASCFIL.ZIP / TABLE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-01  |  10.3 KB  |  467 lines

  1. //*                         Table.Cpp
  2. //*
  3. //*    Functions to Handle File Input, Indexing and Searching Methods for
  4. //*    use with Ascii Non-delimited Files... ( or delimited files )
  5. //*
  6. //***************************************************************************
  7.  
  8. #include <io.h>
  9. #include <fcntl.h>
  10. #include <sys\stat.h>
  11. #include <string.h>
  12. #include "table.h"
  13.  
  14. int         Table::usage=0;
  15. IndexTable* Table::pIndex[10];
  16. Table*      Table::pTable[10];
  17.  
  18.  
  19. //**************************************************************************
  20. Table::Table(char *file, Record *record)
  21. {
  22.     if (!usage)
  23.         for (int i=0; i<10; i++)
  24.         {
  25.              pIndex[i]       = NULL;
  26.              pTable[i]       = NULL;
  27.         }
  28.  
  29.     pRecord     = record;
  30.     cursor        = 0;
  31.     fileSize    = 0; 
  32.     recCount    = 0; 
  33.     recLength    = pRecord->Length(); 
  34.  
  35.     hFile    = _open(file,O_RDONLY|O_BINARY);
  36.         if (hFile>0)
  37.         {
  38.         fileSize = filelength(hFile);
  39.         recCount = fileSize/recLength;
  40.     }
  41.     usage++;
  42. }
  43.  
  44.  
  45. //**************************************************************************
  46. Table::~Table(void)
  47. {
  48.     usage--;
  49.     if (hFile>0)
  50.         _close(hFile);
  51.  
  52.     for (int i=0; i<10; i++)
  53.         {
  54.             if (pTable[i]==this && pIndex[i])
  55.             {
  56.                   delete pIndex[i];
  57.                   unlink(indexName(i));
  58.             }
  59.         }
  60. }
  61.  
  62.  
  63. //**************************************************************************
  64. int Table::Get(void)
  65. {
  66.     if (recCount<1)
  67.         return(TBL_EMPTY);
  68.  
  69.     lseek(hFile,cursor*recLength,SEEK_SET);
  70.     _read(hFile,pRecord->Buffer,recLength);
  71.     return(TBL_OK);
  72. }
  73.  
  74.  
  75. //**************************************************************************
  76. int Table::gotoFirst(int ihandle)
  77. {
  78.     if (recCount<1)
  79.         return(TBL_EMPTY);
  80.  
  81.         cursor = ihandle == -1 ? 0 : pIndex[ihandle]->getFirst();
  82.     return(TBL_OK);
  83. }
  84.  
  85. //**************************************************************************
  86. int Table::gotoLast(int ihandle)
  87. {
  88.     if (recCount<1)
  89.         return(TBL_EMPTY);
  90.  
  91.     cursor = ihandle==-1 ? recCount-1 : pIndex[ihandle]->getLast();
  92.     return(TBL_OK);
  93. }
  94.  
  95.  
  96. //**************************************************************************
  97. int Table::gotoNext(int ihandle)
  98. {
  99.     if (recCount<1)
  100.         return(TBL_EMPTY);
  101.  
  102.         if (ihandle == -1)
  103.         {
  104.         if (cursor+1==recCount)
  105.             return(TBL_END);
  106.         cursor++;
  107.     }
  108.         else
  109.            {
  110.         long next = pIndex[ihandle]->getNext();
  111.         if (next==-1)
  112.             return(TBL_END);
  113.         cursor=next;
  114.            }
  115.     return(TBL_OK);
  116. }
  117.  
  118.  
  119. //**************************************************************************
  120. int Table::gotoPrev(int ihandle)
  121. {
  122.     if (recCount<1)
  123.         return(TBL_EMPTY);
  124.  
  125.         if (ihandle == -1)
  126.         {
  127.              if (cursor==0)
  128.                   return(TBL_BEGIN);
  129.              cursor--;
  130.     }
  131.         else
  132.            {
  133.         long prev = pIndex[ihandle]->getPrev();
  134.         if (prev==-1)
  135.             return(TBL_END);
  136.         cursor=prev;
  137.            }
  138.  
  139.     return(TBL_OK);
  140. }
  141.  
  142.  
  143. //**************************************************************************
  144. int Table::gotoRecNum(long recnum)
  145. {
  146.     if (recCount<1)
  147.         return(TBL_EMPTY);
  148.  
  149.     if (recnum>=recCount)
  150.         return(TBL_RANGE);
  151.  
  152.     cursor=recnum;
  153.     return(TBL_OK);
  154. }
  155.  
  156. //**************************************************************************
  157.  
  158. int Table::Search(char *fldName, char *search)
  159. {
  160.      return Search(pRecord->getFieldNum(fldName),search);
  161. }
  162.  
  163.  
  164. //**************************************************************************
  165. int Table::Search(int fldNum, char *search)
  166. {
  167.     if (fldNum>=getRecCount() || fldNum<0)
  168.         return TBL_RANGE;
  169.  
  170.         int     stat;
  171.     long    i;
  172.     char    *fld = new char[pRecord->getFieldWidth(fldNum)+1];
  173.  
  174.         for (i=0,stat=gotoFirst(); stat==TBL_OK; stat=gotoNext())
  175.         {
  176.         Get();
  177.         pRecord->getField(fldNum,fld);
  178.                 if (!strcmp(fld,search))
  179.                 {
  180.             cursor=i;
  181.             delete fld;
  182.             return(TBL_OK);
  183.         }
  184.     }
  185.     delete fld;
  186.     gotoRecNum(cursor);
  187.     Get();
  188.     return(TBL_NOTFOUND);
  189. }
  190.  
  191.  
  192. //**************************************************************************
  193. int Table::Search(char *key, int ihandle)
  194. {
  195.     long found = pIndex[ihandle]->findKey(key);
  196.     if (found<0)
  197.         return(TBL_NOTFOUND);
  198.     cursor=found;
  199.     return(TBL_OK);
  200. }
  201.  
  202. //**************************************************************************
  203. int Table::openIndex(int *fields, int fcount)
  204. {
  205. // Find an empty slot for a new index
  206.     for (int ix = 0 ; ix<10; ix++)
  207.         if (!pIndex[ix])
  208.             break;
  209.  
  210. // No handles available return -1 (invalid handle)
  211.     if (ix>=10)
  212.         return(-1);
  213.  
  214.     pTable[ix]=this;
  215.  
  216.     keySize    =    0;
  217.     for (int i=0; i<fcount; i++) 
  218.         keySize += pRecord->getFieldWidth(fields[i]);
  219.  
  220.     IndexTable *index=new IndexTable(indexName(ix),keySize);
  221.  
  222.     char *key = new char[keySize+1];
  223.  
  224.         for (int stat=gotoFirst(); stat==TBL_OK; stat=gotoNext())
  225.         {
  226.         Get();
  227.         int n=0;
  228.         for (int f=0; f<fcount; f++,n+=pRecord->getFieldWidth(fields[f]))
  229.             pRecord->getField(fields[f],key+n);
  230.         index->addKey(key,cursor);
  231.     }
  232.     pIndex[ix]=index;
  233.     return(ix);
  234. }
  235.  
  236.  
  237. //**************************************************************************
  238. int Table::closeIndex(int ix)
  239. {
  240.         if (pIndex[ix] && pTable[ix]==this)
  241.         {
  242.         delete pIndex[ix];
  243.         pIndex[ix] = NULL;
  244.         pTable[ix] = NULL;
  245.         return(1);
  246.     }
  247.     return(0);
  248. }
  249.  
  250.  
  251. //**************************************************************************
  252. char* Table::indexName(int handle)
  253. {
  254.     static char name[13];
  255.     strcpy(name,"table.ix");
  256.     name[8]=handle+'0';
  257.     name[9]=0;
  258.     return(name);
  259. }
  260.  
  261.  
  262. //**************************************************************************
  263. IndexTable::IndexTable(char *name, int keysize)
  264. {
  265.     unlink(name);
  266.     handle        = open(name,O_RDWR|O_BINARY|O_CREAT,S_IREAD|S_IWRITE);
  267.     keySize     = keysize;
  268.     keyCount    = 0;
  269.         Key             = new char[keySize];
  270. }
  271.  
  272.  
  273. //**************************************************************************
  274. IndexTable::~IndexTable(void)
  275. {
  276.     delete Key;
  277.     close(handle);
  278. }
  279.  
  280.  
  281. //**************************************************************************
  282. void IndexTable::addKey(char *key, long recnum)
  283. {
  284.   char loc;
  285.  
  286.    if (keyCount>0)
  287.    {
  288.      lseek(handle,current=0l,SEEK_SET);
  289.      while(1)
  290.      {
  291.              read(handle,Key,keySize);
  292.              read(handle,&keyData,sizeof(KeyData));
  293.  
  294.              if (memcmp(key,Key,keySize)<=0)
  295.              {
  296.                      if (keyData.left == -1)
  297.                      {
  298.                              keyData.left=keyCount*(keySize+sizeof(KeyData));
  299.                              loc = 'L';
  300.                              break;
  301.                      }
  302.                      else
  303.                              current = lseek(handle,keyData.left,SEEK_SET);
  304.              }
  305.              else
  306.              {
  307.                      if (keyData.right == -1)
  308.                      {
  309.                              keyData.right=keyCount*(keySize+sizeof(KeyData));
  310.                              loc = 'R';
  311.                              break;
  312.                      }
  313.                      else
  314.                              current = lseek(handle,keyData.right,SEEK_SET);
  315.              }
  316.      }
  317.      lseek(handle,current+keySize,SEEK_SET);
  318.      write(handle,&keyData,sizeof(KeyData));
  319.    }
  320.    else {
  321.            loc=0;
  322.            current=-1;
  323.    }
  324.  
  325.    keyData.recnum  = recnum;
  326.    keyData.parent  = current;
  327.    keyData.loc     = loc;
  328.    keyData.left    = -1;
  329.    keyData.right   = -1;
  330.  
  331.    current=lseek(handle,0l,SEEK_END);
  332.    write(handle,key,keySize);
  333.    write(handle,&keyData,sizeof(KeyData));
  334.  
  335.    keyCount++;
  336. }
  337.  
  338.  
  339. //**************************************************************************
  340. long IndexTable::getFirst(long start)
  341. {
  342.     keyData.left = start;
  343.         while(keyData.left != -1)
  344.         {
  345.         current= keyData.left;
  346.         lseek(handle,keyData.left+keySize,SEEK_SET);
  347.         read(handle,&keyData,sizeof(KeyData));
  348.     }
  349.     return(keyData.recnum);
  350. }
  351.  
  352. //**************************************************************************
  353. long IndexTable::getLast(long start)
  354. {
  355.     keyData.right = start;
  356.         while(keyData.right != -1)
  357.         {
  358.         current=keyData.right;
  359.         lseek(handle,keyData.right+keySize,SEEK_SET);
  360.         read(handle,&keyData,sizeof(KeyData));
  361.     }
  362.     return(keyData.recnum);
  363. }
  364.  
  365. //**************************************************************************
  366. long IndexTable::getNext(void)
  367. {
  368.     char prevloc=0;
  369.  
  370.     while(1) {
  371.  
  372.         if (current==-1)
  373.             return(-1);
  374.  
  375.         lseek(handle,current+keySize,SEEK_SET);
  376.         read(handle,&keyData,sizeof(KeyData));
  377.  
  378.         if (prevloc == 'L')
  379.                 return(keyData.recnum);
  380.  
  381.         if (prevloc != 'R' && keyData.right>= 0)
  382.                 return(getFirst(keyData.right));
  383.  
  384.         prevloc = keyData.loc;
  385.         current=keyData.parent;
  386.  
  387.         if (current==-1)
  388.             return(-1);
  389.  
  390.         lseek(handle,keyData.parent+keySize,SEEK_SET);
  391.         read(handle,&keyData,sizeof(KeyData));
  392.  
  393.         if (prevloc=='L')
  394.             return(keyData.recnum);
  395.  
  396.         prevloc = keyData.loc;
  397.         current=keyData.parent;
  398.     }
  399. }
  400.  
  401. //**************************************************************************
  402. long IndexTable::getPrev(void)
  403. {
  404.     char prevloc=0;
  405.  
  406.     while(1) {
  407.  
  408.         if (current==-1)
  409.             return(-1);
  410.  
  411.         lseek(handle,current+keySize,SEEK_SET);
  412.         read(handle,&keyData,sizeof(KeyData));
  413.  
  414.         if (prevloc == 'R')
  415.                 return(keyData.recnum);
  416.  
  417.         if (prevloc != 'L' && keyData.left>= 0)
  418.                 return(getLast(keyData.left));
  419.  
  420.         prevloc = keyData.loc;
  421.         current=keyData.parent;
  422.  
  423.         if (current==-1)
  424.             return(-1);
  425.  
  426.         lseek(handle,keyData.parent+keySize,SEEK_SET);
  427.         read(handle,&keyData,sizeof(KeyData));
  428.  
  429.         if (prevloc=='R')
  430.             return(keyData.recnum);
  431.  
  432.         prevloc = keyData.loc;
  433.         current=keyData.parent;
  434.     }
  435. }
  436.  
  437. //**************************************************************************
  438. long IndexTable::findKey(char *key)
  439. {
  440.     long  location;
  441.  
  442.     lseek(handle,location=0l,SEEK_SET);
  443.     while(1) {
  444.         read(handle,Key,keySize);
  445.         read(handle,&keyData,sizeof(KeyData));
  446.  
  447.                 if (memcmp(key,Key,keySize)==0)
  448.                 {
  449.             current=location;
  450.             return(keyData.recnum);
  451.         }
  452.  
  453.                 if (memcmp(key,Key,keySize)<0)
  454.                 {
  455.             if (keyData.left == -1)
  456.                 return(-1);
  457.             location = lseek(handle,keyData.left,SEEK_SET);
  458.         }
  459.                 else
  460.                    {
  461.             if (keyData.right == -1)
  462.                 return(-1);
  463.             location = lseek(handle,keyData.right,SEEK_SET);
  464.                    }
  465.     }
  466. }
  467.